home *** CD-ROM | disk | FTP | other *** search
- /*----------------------------------------------------------------------------
-
- group.c
-
- This module handles group windows.
-
- Copyright © 1994-1995, Northwestern University.
-
- ----------------------------------------------------------------------------*/
-
- #include <string.h>
- #include <ctype.h>
- #include <stdio.h>
-
- #include "glob.h"
- #include "group.h"
- #include "wind.h"
- #include "newsrc.h"
- #include "newswatcher.h"
- #include "menus.h"
- #include "next.h"
- #include "mark.h"
- #include "newart.h"
- #include "subscribe.h"
- #include "search.h"
- #include "ldef.h"
- #include "olddrag.h"
- #include "dialog.h"
- #include "subject.h"
- #include "drawutil.h"
- #include "memutil.h"
- #include "listutil.h"
- #include "windutil.h"
- #include "tescroll.h"
- #include "strutil.h"
- #include "fileutil.h"
- #include "dragutil.h"
- #include "resutil.h"
- #include "key.h"
- #include "ic.h"
- #include "help.h"
-
-
-
- #define kMaxFetchDialog 139
-
- #define kFindDlg 157
- #define kFindPattern 4
- #define kStartAtBeginning 5
-
- #define kMaxArticles 4
-
- #define kMinWindowWidth 200 /* minimum window width */
-
-
-
- static Boolean gFirstListClickCall; /* true if first call to ClickLoop function */
- static OSErr gClickLoopErr; /* click loop error code */
-
- static WindowPtr gDragSrcWindow; /* pointer to drag source window, or nil
- is source was different application */
- static WindowPtr gDragDestWindow; /* pointer to drag destination window */
- static Boolean gDragOptionKey; /* true if option-drag */
- static short gDragDestRow; /* current drag destination row */
- static short gFinalDragDestRow; /* final drag destination row */
- static Handle gDragData; /* handle to drag data */
-
- static ListClickLoopUPP gGroupListClickLoopUPP;
- static ListClickLoopUPP gOldListClickLoopUPP;
- static DragTrackingHandlerUPP gHandleTrackingUPP;
- static DragReceiveHandlerUPP gHandleReceiveUPP;
-
-
-
- /*----------------------------------------------------------------------------
- DoFindDialog
-
- Present the find dialog.
-
- Exit: function result = error code.
- gFindPattern = search string.
- ----------------------------------------------------------------------------*/
-
- OSErr DoFindDialog (void)
- {
- CStr255 pattern;
- DialogPtr dlg = nil;
- short item;
- OSErr err = noErr;
- EventRecord ev;
-
- err = MyGetNewDialog(kFindDlg, ok, cancel, &dlg);
- if (err != noErr) return err;
- RestoreMovableModalDialogPosition(dlg, gPrefs.findLoc);
- strcpy(pattern, gFindPattern);
-
- DlgSetCString(dlg, kFindPattern, pattern);
- SetItemMaxLength(dlg, kFindPattern, 255);
- DlgSetCheck(dlg, kStartAtBeginning, gPrefs.startFindAtBeginning);
- SelectDialogItemText(dlg, kFindPattern, 0, 255);
-
- do {
- DlgEnableItem(dlg, ok, *pattern != 0);
- MyMovableModalDialog(dlg, DialogFilter, &item);
- switch (item) {
- case kFindPattern:
- DlgGetCString(dlg, kFindPattern, pattern);
- break;
- case kStartAtBeginning:
- DlgToggleCheck(dlg, kStartAtBeginning);
- break;
- }
- } while (item != ok && item != cancel);
-
- if (item == ok) {
- strcpy(gFindPattern, pattern);
- gPrefs.startFindAtBeginning = DlgGetCheck(dlg, kStartAtBeginning);
- }
-
- SaveMovableModalDialogPosition(dlg, &gPrefs.findLoc);
- err = DoClose(dlg);
- if (err != noErr) return err;
-
- while (WaitNextEvent(activMask | updateMask | osMask, &ev, 0, nil))
- HandleEvent(&ev);
-
- if (item == cancel) return userCanceledErr;
-
- return noErr;
- }
-
-
-
- /*----------------------------------------------------------------------------
- BuildGroupScrapData
-
- Build scrap data for all the selected groups in a group list window.
-
- Entry: wind = pointer to group list window.
-
- Exit: function result = error code.
- *privateScrap = handle to private type 'NNTP' scrap data for selected groups.
- *publicScrap = handle to public type 'TEXT' scrap data for selected groups.
-
- The scrap data is used for group cut/copy/paste, and as the flavor
- data for group drags.
-
- The format of the private 'NNTP' scrap data is:
-
- Scrap subtype (long): 'GRUP'
- Version number of NewsWatcher which created the scrap data (unsigned long).
- Minimum version number of NewsWatcher which can read this scrap data
- (unsigned long).
- Number of groups in list (long).
-
- For each group in the list:
-
- P-format group name string, rounded up to longword boundary.
- Low article number (long).
- High article number (long).
- Number of unread articles (long).
- Number of items in list of unread articles (long).
- List of unread article ranges (two longs each).
-
- As a special case, for groups copied or dragged from the full group list
- or from the new groups list:
-
- low article number = -1
- high article number = 0
- number of unread articles = 0
- number of items in list of unread articles = 0
-
- When such a group is later inserted into a user group list, we must
- query the server to subscribe to the group.
-
- The public 'TEXT' scrap data is a list of the group names separated by
- commas.
- ----------------------------------------------------------------------------*/
-
- static OSErr BuildGroupScrapData (WindowPtr wind, Handle *privateScrap,
- Handle *publicScrap)
- {
- TWindow **info;
- TGroup **groupArray, theGroup;
- ListHandle theList;
- Handle pri = nil;
- long priAllocated, priNext;
- Handle pub = nil;
- long pubAllocated, pubNext;
- Cell theCell;
- short cellDataLen, index;
- CStr255 groupName;
- OSErr err = noErr;
- unsigned long versNumber;
- Boolean userGroupList;
- long numGroups;
- long groupNameLen;
- long bytesNeeded;
- TUnread **unread;
- long numUnreadPairs;
-
- info = (TWindow**)GetWRefCon(wind);
- groupArray = (**info).groupArray;
- theList = (**info).theList;
- userGroupList = (**info).groupKind == kUserGroup;
- numGroups = NumListItemsSelected(theList);
-
- if (userGroupList) {
- err = UpdateAllUnreadLists(wind);
- if (err != noErr) goto exit;
- }
-
- err = MyNewHandle(1000, &pri);
- if (err != noErr) goto exit;
- priAllocated = 1000;
- priNext = 0;
-
- err = MyNewHandle(1000, &pub);
- if (err != noErr) goto exit;
- pubAllocated = 1000;
- pubNext = 0;
-
- *(OSType*)(*pri + priNext) = 'GRUP';
- priNext += sizeof(OSType);
-
- err = GetVersionNumber(&versNumber);
- if (err != noErr) goto exit;
- *(unsigned long*)(*pri + priNext) = versNumber;
- priNext += sizeof(unsigned long);
-
- *(unsigned long*)(*pri + priNext) = 0x02002043; /* 2.0d43 */
- priNext += sizeof(unsigned long);
-
- *(long*)(*pri + priNext) = numGroups;
- priNext += sizeof(long);
-
- SetPt(&theCell, 0, 0);
-
- while (LGetSelect(true, &theCell, theList)) {
-
- cellDataLen = 2;
- LGetCell(&index, &cellDataLen, theCell, theList);
- theGroup = (*groupArray)[index];
- strcpy(groupName, *gGroupNames + theGroup.nameOffset);
- groupNameLen = strlen(groupName);
-
- bytesNeeded = groupNameLen;
- if (pubNext != 0) bytesNeeded += 2;
- if (pubNext + bytesNeeded > pubAllocated) {
- pubAllocated += 1000;
- err = MySetHandleSize(pub, pubAllocated);
- if (err != noErr) goto exit;
- }
- if (pubNext != 0) {
- BlockMoveData(", ", *pub + pubNext, 2);
- pubNext += 2;
- }
- BlockMoveData(groupName, *pub + pubNext, groupNameLen);
- pubNext += groupNameLen;
-
- bytesNeeded = groupNameLen + 1;
- bytesNeeded = ((bytesNeeded + 3) >> 2) << 2;
- bytesNeeded += 4*sizeof(long);
- if (userGroupList) {
- numUnreadPairs = 0;
- for (unread = theGroup.unread; unread != nil; unread = (**unread).next) {
- bytesNeeded += 2*sizeof(long);
- numUnreadPairs++;
- }
- }
- if (priNext + bytesNeeded > priAllocated) {
- priAllocated += bytesNeeded > 1000 ? bytesNeeded : 1000;
- err = MySetHandleSize(pri, priAllocated);
- if (err != noErr) goto exit;
- }
- *(*pri + priNext) = groupNameLen;
- priNext++;
- BlockMoveData(groupName, *pri + priNext, groupNameLen);
- priNext += groupNameLen;
- priNext = ((priNext + 3) >> 2) << 2;
- if (userGroupList) {
- *(long*)(*pri + priNext) = theGroup.firstMess;
- priNext += 4;
- *(long*)(*pri + priNext) = theGroup.lastMess;
- priNext += 4;
- *(long*)(*pri + priNext) = theGroup.numUnread;
- priNext += 4;
- *(long*)(*pri + priNext) = numUnreadPairs;
- priNext += 4;
- for (unread = theGroup.unread; unread != nil; unread = (**unread).next) {
- *(long*)(*pri + priNext) = (**unread).firstUnread;
- priNext += 4;
- *(long*)(*pri + priNext) = (**unread).lastUnread;
- priNext += 4;
- }
- } else {
- *(long*)(*pri + priNext) = -1;
- priNext += 4;
- *(long*)(*pri + priNext) = 0;
- priNext += 4;
- *(long*)(*pri + priNext) = 0;
- priNext += 4;
- *(long*)(*pri + priNext) = 0;
- priNext += 4;
- }
-
- theCell.v++;
-
- }
-
- MySetHandleSize(pri, priNext);
- MySetHandleSize(pub, pubNext);
- *privateScrap = pri;
- *publicScrap = pub;
- return noErr;
-
- exit:
-
- MyDisposeHandle(pri);
- MyDisposeHandle(pub);
- return err;
- }
-
-
-
- /*----------------------------------------------------------------------------
- CheckScrapData
-
- Check scrap data to make sure it is valid. Issue an error message if
- the data is invalid or cannot be read because this version of NewsWatcher
- is too old to understand the data format.
-
- Entry: data = handle to scrap data.
-
- Exit: function result = error code = noErr if valid, userCanceledErr
- if not valid.
- ----------------------------------------------------------------------------*/
-
- OSErr CheckScrapData (Handle data)
- {
- char state;
- Ptr p, pEnd;
- OSType subType;
- unsigned long minVersion, myVersion;
- long numGroups;
- unsigned char groupNameLen;
- long firstMess, lastMess, numUnread;
- long numUnreadPairs, prevLastUnread, firstUnread, lastUnread;
- OSErr err = noErr;
-
- state = MyHGetState(data);
- MyHLock(data);
-
- p = *data;
- pEnd = *data + MyGetHandleSize(data);
-
- subType = *(OSType*)p;
- p += sizeof(OSType);
- if (p > pEnd || subType != 'GRUP') goto exit;
-
- p += sizeof(unsigned long);
- if (p > pEnd) goto exit;
-
- minVersion = *(unsigned long*)p;
- p += sizeof(unsigned long);
- if (p > pEnd) goto exit;
- err = GetVersionNumber(&myVersion);
- if (err != noErr) goto exit;
- if (myVersion < minVersion) goto exit;
-
- numGroups = *(long*)p;
- p += sizeof(long);
- if (p > pEnd) goto exit;
- if (numGroups <= 0 || numGroups > 0x7fff) goto exit;
-
- while (numGroups--) {
-
- groupNameLen = *(unsigned char*)p;
- if (groupNameLen == 0) goto exit;
- groupNameLen++;
- groupNameLen = ((groupNameLen + 3) >> 2) << 2;
- p += groupNameLen;
- if (p > pEnd) goto exit;
-
- firstMess = *(long*)p;
- p += sizeof(long);
- if (p > pEnd || firstMess < -1) goto exit;
-
- lastMess = *(long*)p;
- p += sizeof(long);
- if (p > pEnd || lastMess < 0) goto exit;
-
- numUnread = *(long*)p;
- p += sizeof(long);
- if (p > pEnd || numUnread < 0) goto exit;
-
- numUnreadPairs = *(long*)p;
- p += sizeof(long);
- if (p > pEnd || numUnreadPairs < 0) goto exit;
-
- prevLastUnread = -1;
- while (numUnreadPairs--) {
- firstUnread = *(long*)p;
- p += sizeof(long);
- if (p > pEnd || firstUnread < 0) goto exit;
- lastUnread = *(long*)p;
- p += sizeof(long);
- if (p > pEnd || lastUnread < 0) goto exit;
- if (firstUnread > lastUnread) goto exit;
- if (firstUnread <= prevLastUnread) goto exit;
- prevLastUnread = lastUnread;
- }
- }
-
- if (p != pEnd) goto exit;
-
- MyHSetState(data, state);
- return noErr;
-
- exit:
-
- MyHSetState(data, state);
- ErrorMessageNumber(kStrBadScrapData);
- return userCanceledErr;
- }
-
-
-
- /*----------------------------------------------------------------------------
- DisposeGroupUnreadList
-
- Dispose the unread list for a group.
-
- Entry: theGroup = pointer to group record.
- ----------------------------------------------------------------------------*/
-
- void DisposeGroupUnreadList (TGroup *theGroup)
- {
- TUnread **pUnreadRec, **qUnreadRec;
-
- pUnreadRec = theGroup->unread;
- while (pUnreadRec != nil) {
- qUnreadRec = (**pUnreadRec).next;
- MyDisposeHandle(pUnreadRec);
- pUnreadRec = qUnreadRec;
- }
- theGroup->unread = nil;
- theGroup->numUnread = 0;
- }
-
-
-
- /*----------------------------------------------------------------------------
- DisposeGroupArray
-
- Dispose a group array.
-
- Entry: groupArray = handle to group array.
- numGroups = number of groups in array.
- ----------------------------------------------------------------------------*/
-
- void DisposeGroupArray (TGroup **groupArray, short numGroups)
- {
- TGroup *p, *pEnd;
-
- if (groupArray == nil) return;
- MyHLock(groupArray);
- for (p = *groupArray, pEnd = p + numGroups; p < pEnd; p++)
- DisposeGroupUnreadList(p);
- MyDisposeHandle(groupArray);
- }
-
-
-
- /*----------------------------------------------------------------------------
- FixHeight
-
- Round down window height to an exact multiple of lines.
-
- Entry: wind = pointer to group window.
- *height = window height.
-
- Exit: *height = adjusted window height
- ----------------------------------------------------------------------------*/
-
- static void FixHeight (WindowPtr wind, short *height)
- {
- TWindow **info;
- short panelHeight, lineHeight, adjust;
-
- info = (TWindow**)GetWRefCon(wind);
- panelHeight = (**info).panelHeight;
- lineHeight = GetFontLineHeight(wind);
- adjust = panelHeight + 15;
- *height = (*height - adjust) / lineHeight * lineHeight + adjust;
- }
-
-
-
- /*----------------------------------------------------------------------------
- MinHeight
-
- Compute the minimum height of a group window.
-
- Entry: wind = pointer to group window.
- ----------------------------------------------------------------------------*/
-
- static short MinHeight (WindowPtr wind)
- {
- TWindow **info;
- short lineHeight, height, extra;
-
- info = (TWindow**)GetWRefCon(wind);
- lineHeight = GetFontLineHeight(wind);
- extra = lineHeight + 15;
- if (extra < 65) extra = 65 + lineHeight;
- height = (**info).panelHeight + extra;
- FixHeight(wind, &height);
- return height;
- }
-
-
-
- /*----------------------------------------------------------------------------
- Scroll
-
- Scroll a group window.
-
- Entry: wind = pointer to group window.
- part = part code.
- ----------------------------------------------------------------------------*/
-
- static void Scroll (WindowPtr wind, short part)
- {
- TWindow **info;
- ListHandle theList;
- short height, numCells;
- Cell theCell;
-
- info = (TWindow**)GetWRefCon(wind);
- theList = (**info).theList;
- height = (**theList).visible.bottom - (**theList).visible.top;
- numCells = (**theList).dataBounds.bottom;
- switch (part) {
- case inUpButton:
- case inDownButton:
- SetPt(&theCell, 0, 0);
- if (part == inUpButton) {
- theCell.v = GetFirstSelectedCell(theList);
- theCell.v--;
- if (theCell.v < 0) theCell.v = 0;
- } else {
- theCell.v = GetLastSelectedCell(theList);
- theCell.v++;
- if (theCell.v >= numCells) theCell.v = numCells-1;
- }
- SelectSingleListItem(theList, theCell);
- HandleUpdate(wind);
- MyLAutoScroll(theList);
- break;
- case inPageUp:
- MyLScroll(-(height - 1), theList);
- break;
- case inPageDown:
- MyLScroll(height - 1, theList);
- break;
- case kScrollToHome:
- MyLScroll(-numCells, theList);
- break;
- case kScrollToEnd:
- MyLScroll(numCells, theList);
- break;
- }
- }
-
-
-
- /*----------------------------------------------------------------------------
- ResizeContents
-
- Adjust a group window's contents after a window size change (grow
- or zoom).
-
- Entry: wind = pointer to group window.
- ----------------------------------------------------------------------------*/
-
- static void ResizeContents (WindowPtr wind)
- {
- TWindow **info;
- short width, height, panelHeight;
- ListHandle theList;
- Point x;
-
- info = (TWindow**)GetWRefCon(wind);
- panelHeight = (**info).panelHeight;
- theList = (**info).theList;
- width = wind->portRect.right;
- height = wind->portRect.bottom;
-
- LSize(width-15, height-15-panelHeight, theList);
- SetPt(&x, width-15, (**theList).cellSize.v);
- LCellSize(x, theList);
-
- InvalRect(&wind->portRect);
- }
-
-
-
- /*----------------------------------------------------------------------------
- GroupNameMatchesPattern
-
- Compare a find pattern string to a group name.
-
- Entry: pattern = pointer to find pattern string.
- groupName = pointer to group name.
- patternContainsPeriod = true if pattern string contains a
- period.
-
- Exit: function result = true if group name matches pattern
- ----------------------------------------------------------------------------*/
-
- static Boolean GroupNameMatchesPattern (char *pattern, char *groupName,
- Boolean patternContainsPeriod)
- {
- char *pat, *grp;
-
- if (patternContainsPeriod) {
- pat = pattern;
- grp = groupName;
- while (*pat != 0) {
- if (*pat == '.') {
- while (*grp != 0 && *grp != '.') grp++;
- if (*grp == 0) {
- goto exit;
- } else {
- grp++;
- }
- } else {
- if (toupper(*pat) != toupper(*grp)) goto exit;
- grp++;
- }
- pat++;
- }
- return true;
- }
-
- exit:
-
- return MyIsASubstring(groupName, pattern);
- }
-
-
-
- /*----------------------------------------------------------------------------
- Find
-
- Search a group window for a pattern.
-
- Entry: wind = pointer to group window.
- theCell = first cell to search.
- gFindPattern = pattern.
-
- Exit: function result = error code.
- ----------------------------------------------------------------------------*/
-
- static OSErr Find (WindowPtr wind, Cell theCell)
- {
- TWindow **info;
- TGroup **groupArray;
- ListHandle theList;
- short index, cellDataLen, numCells;
- char *groupName;
- Boolean patternContainsPeriod = false;
- char *p;
- unsigned long tickLongTime;
- Boolean longTime = false;
- OSErr err = noErr;
- char state;
-
- info = (TWindow**)GetWRefCon(wind);
- groupArray = (**info).groupArray;
- theList = (**info).theList;
- numCells = (**theList).dataBounds.bottom;
- for (p = gFindPattern; *p != 0; p++) {
- if (*p == '.') {
- patternContainsPeriod = true;
- break;
- }
- }
- tickLongTime = TickCount() + 30;
- state = MyHGetState(gGroupNames);
- MyHLock(gGroupNames);
- while (theCell.v < numCells) {
- cellDataLen = 2;
- LGetCell(&index, &cellDataLen, theCell, theList);
- groupName = *gGroupNames + (*groupArray)[index].nameOffset;
- if (GroupNameMatchesPattern(gFindPattern, groupName, patternContainsPeriod)) {
- MyHSetState(gGroupNames, state);
- SelectSingleListItem(theList, theCell);
- MyLScrollCenter(theCell, theList);
- return noErr;
- }
- theCell.v++;
- if ((theCell.v & 0xf) == 0) {
- if (!longTime && TickCount() > tickLongTime) longTime = true;
- if (longTime) {
- err = GiveTime(false);
- if (err != noErr) {
- MyHSetState(gGroupNames, state);
- return err;
- }
- }
- }
- }
- MyHSetState(gGroupNames, state);
- SysBeep(0);
- return noErr;
- }
-
-
-
- /*----------------------------------------------------------------------------
- MakeGroupList
-
- Creates a List Manager list for a group window.
-
- Entry: numGroups = number of groups in list.
- theList = handle to list record.
-
- Exit: function result = error code.
- Any previous list is deleted. A new list is created with numGroups
- cells. The cell data is initialized to 0, 1, 2, ..., numGroups-1.
- ----------------------------------------------------------------------------*/
-
- OSErr MakeGroupList (short numGroups, ListHandle theList)
- {
- short i;
- short *pCells;
- short *pCellArray;
- short offset;
- OSErr err = noErr;
-
- if (!MemoryAvailable(4*numGroups)) return memFullErr;
-
- LSetDrawingMode(false, theList);
- LDelRow(0, 0, theList);
- LAddRow(numGroups, 0, theList);
-
- err = MySetHandleSize((**theList).cells, 2*numGroups);
- if (err != noErr) goto exit;
-
- pCells = (short*)*((**theList).cells);
- pCellArray = (**theList).cellArray;
- offset = 0;
-
- for (i=0; i<numGroups; i++) {
- *pCellArray++ = offset;
- *pCells++ = i;
- offset += 2;
- }
- *pCellArray = offset;
- LSetDrawingMode(true, theList);
- return noErr;
-
- exit:
-
- LDelRow(0, 0, theList);
- LSetDrawingMode(true, theList);
- return err;
- }
-
-
-
- /*----------------------------------------------------------------------------
- CanAcceptDrag
-
- Figure out whether a dragged object can be accepted by a user group
- list window.
-
- Entry: theDrag = drag reference
-
- Exit: function result = true if this object can be accepted by a user
- group list window.
- ----------------------------------------------------------------------------*/
-
- static Boolean CanAcceptDrag (DragReference theDrag)
- {
- unsigned short numItems;
- ItemReference theItem;
- FlavorFlags theFlags;
- OSErr err = noErr;
- short i;
-
- CountDragItems(theDrag, &numItems);
- for (i = 1; i <= numItems; i++) {
- GetDragItemReferenceNumber(theDrag, i, &theItem);
- err = GetFlavorFlags(theDrag, theItem, kNewsWatcherSignature, &theFlags);
- if (err != noErr) return false;
- }
- return true;
- }
-
-
-
- /*----------------------------------------------------------------------------
- HandleTracking
-
- Drag Manager tracking handler for user group list windows.
-
- Entry: message = tracking message from Drag Manager.
- wind = pointer to user group list window.
- handlerRefCon = reference constant (nil).
- theDrag = drag reference.
-
- Exit: function result = error code.
- ----------------------------------------------------------------------------*/
-
- static pascal OSErr HandleTracking (DragTrackingMessage message,
- WindowPtr wind, void *handlerRefCon, DragReference theDrag)
- {
- TWindow **info;
- ListHandle theList;
- Rect rView, contentRect, visible, dataBounds;
- Point where;
- DragAttributes attributes;
- static Boolean canAcceptDrag;
- static Boolean hilite;
- short newDestRow;
- RgnHandle rgn = nil;
- Boolean inContentRect, leftSender, inSender, canAutoScroll;
- short scrollDelta;
- static short prevScrollDelta;
- static long scrollTickCount;
-
- if (gLongOperation || gInDialog) return userCanceledErr;
-
- if (gDragErr != noErr) message = dragTrackingLeaveWindow;
-
- GetDragAttributes(theDrag, &attributes);
- leftSender = (attributes & dragHasLeftSenderWindow) != 0;
- inSender = (attributes & dragInsideSenderWindow) != 0;
- info = (TWindow**)GetWRefCon(wind);
- theList = (**info).theList;
- visible = (**theList).visible;
- dataBounds = (**theList).dataBounds;
- rView = (**theList).rView;
- contentRect = rView;
- contentRect.top = 0;
- contentRect.bottom = wind->portRect.bottom;
-
- /* Note: Apple's "Drag and Drop Human Interface Guidelines" prohibit autoscrolling
- unless the source and destination windows are the same and the window is
- frontmost. I do not like this rule, and have deliberately broken it. I permit
- autoscrolling inactive windows during group drags. */
-
- /* canAutoScroll = inSender && wind == FrontWindow();*/
- canAutoScroll = true;
-
- switch (message) {
-
- case dragTrackingEnterHandler:
-
- break;
-
- case dragTrackingEnterWindow:
-
- canAcceptDrag = CanAcceptDrag(theDrag);
- hilite = false;
- gDragDestRow = -1;
- prevScrollDelta = 0;
- break;
-
- case dragTrackingInWindow:
-
- if (!canAcceptDrag) break;
- GetDragMouse(theDrag, &where, nil);
- GlobalToLocal(&where);
- inContentRect = PtInRect(where, &contentRect);
- if (inContentRect) {
- if (leftSender && !hilite) {
- rgn = NewRgn();
- RectRgn(rgn, &rView);
- ShowDragHilite(theDrag, rgn, true);
- DisposeRgn(rgn);
- hilite = true;
- }
- scrollDelta = 0;
- if (canAutoScroll && gDragDestRow >= 0) {
- if (where.v < rView.top && visible.top > 0) {
- scrollDelta = -1;
- } else if (where.v > rView.bottom &&
- visible.bottom < dataBounds.bottom)
- {
- scrollDelta = +1;
- }
- }
- if (scrollDelta == prevScrollDelta) {
- if (scrollDelta != 0 && TickCount() - scrollTickCount < 10)
- scrollDelta = 0;
- } else {
- prevScrollDelta = scrollDelta;
- scrollDelta = 0;
- scrollTickCount = TickCount();
- }
- if (scrollDelta != 0) {
- DrawListDividingLine(theList, gDragDestRow);
- gDragDestRow = -1;
- gDragErr = DragPreScroll(theDrag, 0,
- -scrollDelta * (**theList).cellSize.v);
- if (gDragErr != noErr) return gDragErr;
- MyLScroll(scrollDelta, theList);
- gDragErr = DragPostScroll(theDrag);
- if (gDragErr != noErr) return gDragErr;
- }
- newDestRow = ListDestinationRow(theList, where);
- if (newDestRow != gDragDestRow) {
- if (gDragDestRow >= 0) DrawListDividingLine(theList, gDragDestRow);
- gDragDestRow = newDestRow;
- DrawListDividingLine(theList, gDragDestRow);
- }
- } else {
- if (gDragDestRow >= 0) {
- DrawListDividingLine(theList, gDragDestRow);
- gDragDestRow = -1;
- }
- if (hilite) {
- HideDragHilite(theDrag);
- hilite = false;
- }
- prevScrollDelta = 0;
- }
- break;
-
- case dragTrackingLeaveWindow:
-
- if (gDragDestRow >= 0) DrawListDividingLine(theList, gDragDestRow);
- gDragDestRow = -1;
- if (hilite) HideDragHilite(theDrag);
- hilite = false;
- prevScrollDelta = 0;
- break;
-
- case dragTrackingLeaveHandler:
-
- break;
-
- }
-
- return noErr;
- }
-
-
-
- /*----------------------------------------------------------------------------
- HandleReceivePostProcessor
-
- Drag Manager receive handler post processor for user group list windows.
-
- Entry: gDragSrcWindow = pointer to drag source window, or nil if
- source was different application.
- gDragDestWindow = pointer to destination window.
- gDragOptionKey = true if option-drag.
- gFinalDragDestRow = final drag destination row.
- gDragData = handle to drag data if source was different application.
-
- Exit: function result = error code.
-
- Note: User interaction and network transactions are permitted in
- this function.
- ----------------------------------------------------------------------------*/
-
- static OSErr HandleReceivePostProcessor (void)
- {
- TWindow **srcInfo;
- TGroupWindowKind srcKind;
- Boolean changed;
- OSErr err = noErr;
-
- if (gDragSrcWindow == nil) {
- err = CopyGroupsFromScrap(gDragData, gDragDestWindow, gFinalDragDestRow);
- MyDisposeHandle(gDragData);
- return err;
- }
-
- srcInfo = (TWindow**)GetWRefCon(gDragSrcWindow);
- srcKind = (**srcInfo).groupKind;
-
- switch (srcKind) {
-
- case kUserGroup:
-
- if (gDragDestWindow == gDragSrcWindow) {
- MoveSelectedListCells((**srcInfo).theList, gFinalDragDestRow, &changed);
- if (changed) (**srcInfo).changed = true;
- } else {
- err = CopyOrMoveSelectedGroups(gDragSrcWindow, gDragDestWindow,
- gFinalDragDestRow, gDragOptionKey);
- if (err != noErr) return err;
- }
- break;
-
- case kFullGroup:
- case kNewGroup:
-
- err = CopyOrMoveSelectedGroups(gDragSrcWindow, gDragDestWindow,
- gFinalDragDestRow, true);
- if (err != noErr) return err;
- break;
- }
-
- return noErr;
- }
-
-
-
- /*----------------------------------------------------------------------------
- MergeGroupScrapData
-
- Merge two blocks of group scrap data.
-
- Entry: data1 = handle to first scrap data.
- data2 = handle to second scrap data.
-
- Exit: function result = error code.
- data1 = handle to merged scrap data.
- ----------------------------------------------------------------------------*/
-
- static OSErr MergeGroupScrapData (Handle data1, Handle data2)
- {
- long len1, len2;
- OSErr err = noErr;
-
- len1 = MyGetHandleSize(data1);
- len2 = MyGetHandleSize(data2);
- if (len2 < 16) {
- if (len1 < 4) return noErr;
- *(OSType*)(*data1) = 'XXXX';
- return noErr;
- }
- err = MySetHandleSize(data1, len1 + len2 - 16);
- if (err != noErr) return err;
- BlockMoveData(*data2 + 16, *data1 + len1, len2 - 16);
- *(long*)(*data1 + 12) += *(long*)(*data2 + 12);
- return noErr;
- }
-
-
-
- /*----------------------------------------------------------------------------
- GetGroupDragScrapData
-
- Get the group scrap data at the end of a drag.
-
- Entry: theDrag = drag reference.
-
- Exit: function result = error code.
- *dragData = handle to drag data.
- ----------------------------------------------------------------------------*/
-
- OSErr GetGroupDragScrapData (DragReference theDrag, Handle *dragData)
- {
- unsigned short numItems;
- ItemReference theItem;
- OSErr err = noErr;
- short i;
- Handle data = nil, itemData = nil;
-
- CountDragItems(theDrag, &numItems);
- for (i = 1; i <= numItems; i++) {
- err = GetDragItemReferenceNumber(theDrag, i, &theItem);
- if (err != noErr) goto exit;
- err = MyGetFlavorDataHandle(theDrag, theItem, kNewsWatcherSignature,
- &itemData);
- if (err != noErr) goto exit;
- if (i == 1) {
- data = itemData;
- itemData = nil;
- } else {
- err = MergeGroupScrapData(data, itemData);
- if (err != noErr) goto exit;
- MyDisposeHandle(itemData);
- itemData = nil;
- }
- }
-
- *dragData = data;
- return noErr;
-
- exit:
-
- MyDisposeHandle(data);
- MyDisposeHandle(itemData);
- return err;
- }
-
-
-
- /*----------------------------------------------------------------------------
- HandleReceive
-
- Drag Manager receive handler for user group list windows.
-
- Entry: wind = pointer to user group list window.
- handlerRefCon = reference constant (nil).
- theDrag = drag reference.
-
- Exit: function result = error code.
-
- Note: No user interaction or network transactions are permitted in
- this function.
- ----------------------------------------------------------------------------*/
-
- static pascal OSErr HandleReceive (WindowPtr wind, void *handlerRefCon,
- DragReference theDrag)
- {
- DragAttributes attributes;
- short mouseDownModifiers, mouseUpModifiers;
-
- if (gLongOperation || gInDialog || gDragErr != noErr ||
- gDragDestRow < 0 || !CanAcceptDrag(theDrag)) goto exit;
-
- GetDragAttributes(theDrag, &attributes);
- if ((attributes & dragInsideSenderApplication) == 0) gDragSrcWindow = nil;
-
- gDragDestWindow = wind;
-
- GetDragModifiers(theDrag, nil, &mouseDownModifiers, &mouseUpModifiers);
- gDragOptionKey = (mouseDownModifiers & optionKey) != 0 ||
- (mouseUpModifiers & optionKey) != 0;
-
- gFinalDragDestRow = gDragDestRow;
-
- if (gDragSrcWindow == nil) {
- gDragErr = GetGroupDragScrapData(theDrag, &gDragData);
- if (gDragErr != noErr) goto exit;
- }
-
- gDragPostProcessor = HandleReceivePostProcessor;
-
- return noErr;
-
- exit:
-
- HandleTracking(dragTrackingLeaveWindow, wind, handlerRefCon, theDrag);
- return dragNotAcceptedErr;
- }
-
-
-
- /*----------------------------------------------------------------------------
- AddDragItems
-
- Add the drag items for dragging groups.
-
- Entry: dragRef = drag reference.
-
- Exit: function result = error code.
- ----------------------------------------------------------------------------*/
-
- static OSErr AddDragItems (DragReference dragRef)
- {
- Handle privateScrap = nil, publicScrap = nil;
- OSErr err = noErr;
-
- err = BuildGroupScrapData(gDragSrcWindow, &privateScrap, &publicScrap);
- if (err != noErr) goto exit;
-
- MyHLock(privateScrap);
- err = AddDragItemFlavor(dragRef, 1, kNewsWatcherSignature, *privateScrap,
- MyGetHandleSize(privateScrap), 0);
- if (err != noErr) goto exit;
- MyDisposeHandle(privateScrap);
- privateScrap = nil;
-
- MyHLock(publicScrap);
- err = AddDragItemFlavor(dragRef, 1, 'TEXT', *publicScrap,
- MyGetHandleSize(publicScrap), 0);
- if (err != noErr) goto exit;
- MyDisposeHandle(publicScrap);
-
- return noErr;
-
- exit:
-
- MyDisposeHandle(privateScrap);
- MyDisposeHandle(publicScrap);
- return err;
- }
-
-
-
- /*----------------------------------------------------------------------------
- CheckForDragToTrash
-
- If the user dragged groups to the trash, unsubscribe.
-
- Entry: dragRef = drag reference.
- ----------------------------------------------------------------------------*/
-
- static void CheckForDragToTrash (DragReference dragRef)
- {
- TWindow **info;
-
- info = (TWindow**)GetWRefCon(gDragSrcWindow);
- if ((**info).groupKind != kUserGroup) return;
-
- if (!DragTargetWasTrash(dragRef)) return;
-
- UnsubscribeSelected(gDragSrcWindow);
- }
-
-
-
- /*----------------------------------------------------------------------------
- GroupListClickLoop
-
- The click loop routine for group lists when we have the Drag Manager.
- It initiates group drags.
-
- Exit: function result = true if mouse button still down, false
- if mouse button released.
- ----------------------------------------------------------------------------*/
-
- static Boolean GroupListClickLoop (void)
- {
- TWindow **info;
- ListHandle theList;
- OSErr err = noErr;
- DragReference dragRef;
- Boolean haveDragRef = false;
- RgnHandle dragRgn = nil;
-
- info = (TWindow**)GetWRefCon(gDragSrcWindow);
- theList = (**info).theList;
-
- if (gFirstListClickCall) {
- gFirstListClickCall = false;
- return true;
- }
-
- if (WaitMouseMoved(gCurEvent.where)) {
- gDidDrag = true;
- err = NewDrag(&dragRef);
- if (err != noErr) goto exit;
- haveDragRef = true;
- err = AddDragItems(dragRef);
- if (err != noErr) goto exit;
- BuildListSelectedCellsDragRegion(theList, &dragRgn);
- gDragDestRow = -1;
- err = TrackDrag(dragRef, &gCurEvent, dragRgn);
- if (err != noErr) goto exit;
- DisposeRgn(dragRgn);
- CheckForDragToTrash(dragRef);
- DisposeDrag(dragRef);
- }
-
- return false;
-
- exit:
-
- if (dragRgn != nil) DisposeRgn(dragRgn);
- if (haveDragRef) DisposeDrag(dragRef);
- gClickLoopErr = err;
- return false;
- }
-
-
-
- /*----------------------------------------------------------------------------
- MakeNewWindow
-
- Create a new group window.
-
- Entry: groupKind = kind of group window.
- title = window title.
-
- Exit: function result = error code.
- *theWindow = pointer to new window.
- ----------------------------------------------------------------------------*/
-
- static OSErr MakeNewWindow (TGroupWindowKind groupKind, StringPtr title,
- WindowPtr *theWindow)
- {
- short width, height;
- WindowPtr wind = nil;
- TWindow **info;
- ListHandle theList;
- Point thePt;
- Rect listRect, sizeRect;
- short panelHeight;
- OSErr err = noErr;
- GrafPtr port;
-
- GetPort(&port);
-
- MyICReadSharedPrefs(kICListFont);
-
- err = CreateNewWindow(kGroup, title, gPrefs.listFont, gPrefs.listSize, &wind);
- if (err != noErr) return err;
- SetPort(wind);
- info = (TWindow**)GetWRefCon(wind);
- panelHeight = GetFontLineHeight(wind) + 9;
- (**info).panelHeight = panelHeight;
- (**info).groupKind = groupKind;
- width = kMinWindowWidth;
- height = MinHeight(wind);
- PositionNewWindow(wind, width, height);
-
- SetPt(&thePt, 0, 0);
- SetRect(&sizeRect, 0, 0, 1, 0);
- listRect = wind->portRect;
- listRect.top += panelHeight;
- listRect.right -= 15;
- listRect.bottom -= 15;
- theList = MyLNew(&listRect, &sizeRect, thePt, kLDEFProc, wind, false,
- true, false, true);
- (**theList).indent.h = 4;
- (**theList).selFlags |= lNoNilHilite;
- (**theList).refCon = (long)gListDefFuncUPP;
- (**info).theList = theList;
- (**info).vScroll = (**theList).vScroll;
-
- if (groupKind == kUserGroup && gHaveDragMgr) {
- err = InstallTrackingHandler(gHandleTrackingUPP, wind, nil);
- if (err != noErr) goto exit;
- err = InstallReceiveHandler(gHandleReceiveUPP, wind, nil);
- if (err != noErr) goto exit;
- }
-
- *theWindow = wind;
- SetPort(port);
- return noErr;
-
- exit:
-
- DoClose(wind);
- return err;
- }
-
-
-
- /*----------------------------------------------------------------------------
- MakeUserGroupWindow
-
- Create a new user group window.
-
- Entry: title = window title.
- groupArray = handle to group array, or nil to create an empty one.
- numGroups = number of groups in group array.
- pos = pointer to saved window position.
-
- Exit: function result = error code.
- *theWindow = pointer to new window.
- ----------------------------------------------------------------------------*/
-
- OSErr MakeUserGroupWindow (StringPtr title, TGroup **groupArray, short numGroups,
- TSavedWindPos *pos, WindowPtr *theWindow)
- {
- WindowPtr wind = nil;
- TWindow **info;
- ListHandle theList;
- Point theCell;
- short cellDataLen, groupIndex, numCells, wid;
- OSErr err = noErr;
- GrafPtr port;
- Boolean needsZooming;
-
- GetPort(&port);
-
- err = MakeNewWindow(kUserGroup, title, &wind);
- if (err != noErr) return err;
- SetPort(wind);
- info = (TWindow**)GetWRefCon(wind);
- theList = (**info).theList;
- if (groupArray == nil) {
- err = MyNewHandle(0, &groupArray);
- if (err != noErr) goto exit;
- (**info).groupArray = groupArray;
- } else {
- (**info).groupArray = groupArray;
- (**info).numGroups = numGroups;
- err = MakeGroupList(numGroups, theList);
- if (err != noErr) goto exit;
- theCell.h = 0;
- numCells = (**theList).dataBounds.bottom;
- for (theCell.v = 0; theCell.v < numCells; theCell.v++) {
- cellDataLen = 2;
- LGetCell(&groupIndex, &cellDataLen, theCell, theList);
- if ((*groupArray)[groupIndex].numUnread > 0) break;
- }
- if (theCell.v < numCells) {
- MyLSetSelect(true, theCell, theList);
- MyLAutoScroll(theList);
- }
- }
- wid = CharWidth('9');
- (**info).groupNameHCoord = 6 * wid;
- (**info).numUnreadHCoord = 4 * wid;
-
- RestoreWindPos(wind, pos, &needsZooming);
- ResizeContents(wind);
- if (needsZooming) {
- err = DoZoom(wind, inZoomOut);
- if (err != noErr) goto exit;
- }
- (**info).movedSinceLastSave = false;
-
- MyShowWindow(wind);
- *theWindow = wind;
- SetPort(port);
- return noErr;
-
- exit:
-
- DoClose(wind);
- SetPort(port);
- return err;
- }
-
-
-
- /*----------------------------------------------------------------------------
- MakeNewUntitledUserGroupWindow
-
- Create a new untitled user group list window.
-
- Exit: function result = error code.
- *wind = pointer to new window.
- ----------------------------------------------------------------------------*/
-
- OSErr MakeNewUntitledUserGroupWindow (WindowPtr *wind)
- {
- CStr255 untitled, title, xTitle;
- WindowPtr theWind;
- Boolean conflict;
- TSavedWindPos pos;
- short i;
-
- GetCString(kStrUntitled, untitled);
-
- for (i = 1; ; i++) {
- if (i == 1) {
- strcpy(title, untitled);
- } else {
- sprintf(title, "%s %d", untitled, i);
- }
- conflict = false;
- theWind = FrontWindow();
- while (theWind != nil) {
- GetWTitle(theWind, (StringPtr)xTitle);
- p2cstr((StringPtr)xTitle);
- if (strcmp(title, xTitle) == 0) {
- conflict = true;
- break;
- }
- theWind = (WindowPtr)((WindowPeek)theWind)->nextWindow;
- }
- if (!conflict) break;
- }
-
- c2pstr(title);
- pos.valid = false;
- return MakeUserGroupWindow((StringPtr)title, nil, 0, &pos, wind);
- }
-
-
-
- /*----------------------------------------------------------------------------
- MakeNewGroupsWindow
-
- Create a new groups list window.
-
- Entry: groupArray = handle to group array.
- numGroups = number of groups in group array.
-
- Exit: function result = error code.
- *theWindow = pointer to new window.
- ----------------------------------------------------------------------------*/
-
- OSErr MakeNewGroupsWindow (TGroup **groupArray, short numGroups, WindowPtr *theWindow)
- {
- WindowPtr wind = nil;
- TWindow **info;
- ListHandle theList;
- Cell theCell;
- Str255 title;
- OSErr err = noErr;
- GrafPtr port;
-
- GetPort(&port);
-
- GetPString(kStrNewGroups, title);
- err = MakeNewWindow(kNewGroup, title, &wind);
- if (err != noErr) return err;
- SetPort(wind);
- info = (TWindow**)GetWRefCon(wind);
- theList = (**info).theList;
- (**info).numGroups = numGroups;
- (**info).groupArray = groupArray;
-
- err = MakeGroupList(numGroups, theList);
- if (err != noErr) goto exit;
-
- SetPt(&theCell,0,0);
- MyLSetSelect(true, theCell, theList);
-
- err = DoZoom(wind, inZoomOut);
- if (err != noErr) goto exit;
- MyShowWindow(wind);
- *theWindow = wind;
- SetPort(port);
- return noErr;
-
- exit:
-
- DoClose(wind);
- SetPort(port);
- return err;
- }
-
-
-
- /*----------------------------------------------------------------------------
- MakeFullGroupWindow
-
- Create the full group list window.
-
- Entry: groupArray = handle to full group array.
- numGroups = number of groups in full group array.
-
- Exit: function result = error code.
- *theWindow = pointer to new window.
- ----------------------------------------------------------------------------*/
-
- OSErr MakeFullGroupWindow (TGroup **groupArray, short numGroups, WindowPtr *theWindow)
- {
- WindowPtr wind = nil;
- TWindow **info;
- ListHandle theList;
- Cell theCell;
- Str255 title;
- OSErr err = noErr;
- GrafPtr port;
- Boolean needsZooming;
-
- GetPort(&port);
-
- GetPString(kStrFullGroupList, title);
- err = MakeNewWindow(kFullGroup, title, &wind);
- if (err != noErr) return err;
- SetPort(wind);
- info = (TWindow**)GetWRefCon(wind);
- theList = (**info).theList;
- (**info).numGroups = numGroups;
- (**info).groupArray = groupArray;
-
- err = MakeGroupList(numGroups, theList);
- if (err != noErr) goto exit;
-
- SetPt(&theCell, 0, 0);
- MyLSetSelect(true, theCell, theList);
-
- RestoreWindPos(wind, &gPrefs.fullGroupWindPos, &needsZooming);
- ResizeContents(wind);
-
- if (gPrefs.fullGroupListVisible) {
- if (needsZooming) {
- err = DoZoom(wind, inZoomOut);
- if (err != noErr) goto exit;
- }
- gMustDoZoomOnShowFullGroupList = false;
- MyShowWindow(wind);
- SetWindowsMenuShowHideFullGroupList(false);
- } else {
- gMustDoZoomOnShowFullGroupList = needsZooming;
- }
-
- *theWindow = wind;
- SetPort(port);
- return noErr;
-
- exit:
-
- DoClose(wind);
- SetPort(port);
- return err;
- }
-
-
-
- /*----------------------------------------------------------------------------
- OpenSelectedCells
-
- Open all the selected groups in a group list window.
-
- Entry: wind = pointer to group list window.
- promptMaxFetch = true to prompt for maximum number of
- articles to fetch.
-
- Exit: function result = error code.
- ----------------------------------------------------------------------------*/
-
- static OSErr OpenSelectedCells (WindowPtr wind, Boolean promptMaxFetch)
- {
- Cell theCell;
- TWindow **info;
- ListHandle theList;
- short *p, *pBegin, numSelected=0, numOpened=0;
- long maxFetch;
- DialogPtr dlg = nil;
- short item;
- OSErr err = noErr;
- Boolean hasArts;
-
- info = (TWindow**)GetWRefCon(wind);
- theList = (**info).theList;
-
- maxFetch = gPrefs.maxFetch;
- if (promptMaxFetch) {
- err = MyGetNewDialog(kMaxFetchDialog, ok, cancel, &dlg);
- if (err != noErr) return err;
- SetItemNumeric(dlg, kMaxArticles);
- SetItemMaxLength(dlg, kMaxArticles, 5);
- SelectDialogItemText(dlg, kMaxArticles, 0, 0);
- MyModalDialog(dlg, gDialogFilterUPP, &item);
- maxFetch = DlgGetNumber(dlg, kMaxArticles);
- if (maxFetch > 15000) maxFetch = 15000;
- if (maxFetch <= 0) maxFetch = 1;
- err = DoClose(dlg);
- if (err != noErr) return err;
- dlg = nil;
- if (item == cancel) return userCanceledErr;
- if (maxFetch == 0) maxFetch = gPrefs.maxFetch;
- err = MarkSelectedGroups(wind, false, maxFetch);
- if (err != noErr) return err;
- }
-
- SetPt(&theCell, 0, (**theList).dataBounds.bottom-1);
- while (theCell.v >= 0) {
- pBegin = (**theList).cellArray;
- p = pBegin + theCell.v;
- while (*p >= 0 && p >= pBegin) p--;
- theCell.v = p - pBegin;
- if (p >= pBegin) {
- err = OpenGroupCell(wind, theCell, maxFetch, &hasArts);
- if (err != noErr) return err;
- numSelected++;
- if (hasArts) numOpened++;
- }
- theCell.v--;
- }
- if (numOpened < numSelected) {
- if (numSelected == 1) {
- if ((**info).groupKind == kUserGroup) {
- NoteMessageNumber(kStrSelGroupNoUnread);
- } else {
- NoteMessageNumber(kStrSelGroupNoArt);
- }
- } else if (numOpened == 0) {
- if ((**info).groupKind == kUserGroup) {
- NoteMessageNumber(kStrNoneUnread);
- } else {
- NoteMessageNumber(kStrNoArts);
- }
- }
- }
- return noErr;
- }
-
-
-
- /*----------------------------------------------------------------------------
- DoNewGroupWindow
-
- Handle the "New Group Window" command.
-
- Exit: function result = error code.
- ----------------------------------------------------------------------------*/
-
- OSErr DoNewGroupWindow (void)
- {
- WindowPtr wind;
-
- return MakeNewUntitledUserGroupWindow(&wind);
- }
-
-
-
- /*----------------------------------------------------------------------------
- DoCut
-
- Handle the "Cut" command for a user group window.
-
- Entry: wind = pointer to user group window.
-
- Exit: function result = error code.
- ----------------------------------------------------------------------------*/
-
- static OSErr DoCut (WindowPtr wind)
- {
- OSErr err = noErr;
- OSErr DoCopy (WindowPtr wind);
-
- err = DoCopy(wind);
- if (err != noErr) return err;
-
- return UnsubscribeSelected(wind);
- }
-
-
-
- /*----------------------------------------------------------------------------
- DoCopy
-
- Handle the "Copy" command for a group window.
-
- Entry: wind = pointer to group window.
-
- Exit: function result = error code.
- ----------------------------------------------------------------------------*/
-
- static OSErr DoCopy (WindowPtr wind)
- {
- OSErr err = noErr;
- Handle privateScrap = nil;
- Handle publicScrap = nil;
-
- err = BuildGroupScrapData(wind, &privateScrap, &publicScrap);
- if (err != noErr) return err;
-
- ZeroScrap();
-
- MyHLockHi(privateScrap);
- PutScrap(MyGetHandleSize(privateScrap), kNewsWatcherSignature, *privateScrap);
- MyDisposeHandle(privateScrap);
-
- MyHLockHi(publicScrap);
- PutScrap(MyGetHandleSize(publicScrap), 'TEXT', *publicScrap);
- MyDisposeHandle(publicScrap);
-
- return noErr;
- }
-
-
-
- /*----------------------------------------------------------------------------
- DoPaste
-
- Handle the "Paste" command for a user group window.
-
- Entry: wind = pointer to user group window.
-
- Exit: function result = error code.
- ----------------------------------------------------------------------------*/
-
- static OSErr DoPaste (WindowPtr wind)
- {
- Handle scrapData = nil;
- OSErr err = noErr;
- long scrapOffset;
-
- err = MyNewHandle(0, &scrapData);
- if (err != noErr) return err;
- if (GetScrap(scrapData, kNewsWatcherSignature, &scrapOffset) <= 0) goto exit;
- err = CopyGroupsFromScrap(scrapData, wind, 0x7fff);
- if (err != noErr) goto exit;
- MyDisposeHandle(scrapData);
- return noErr;
-
- exit:
-
- MyDisposeHandle(scrapData);
- return err;
- }
-
-
-
- /*----------------------------------------------------------------------------
- DoClear
-
- Handle the "Clear" command for a user group window.
-
- Entry: wind = pointer to user group window.
-
- Exit: function result = error code.
- ----------------------------------------------------------------------------*/
-
- static OSErr DoClear (WindowPtr wind)
- {
- return UnsubscribeSelected(wind);
- }
-
-
-
- /*----------------------------------------------------------------------------
- DoSelectAll
-
- Handle the "Select All" command for a group window.
-
- Entry: wind = pointer to group window.
- ----------------------------------------------------------------------------*/
-
- static void DoSelectAll (WindowPtr wind)
- {
- TWindow **info;
-
- info = (TWindow**)GetWRefCon(wind);
- SelectOrDeselectAllListItems((**info).theList, true);
- }
-
-
-
- /*----------------------------------------------------------------------------
- DoDeselectAll
-
- Handle the "Deselect All" command for a group window.
-
- Entry: wind = pointer to group window.
- ----------------------------------------------------------------------------*/
-
- static void DoDeselectAll (WindowPtr wind)
- {
- TWindow **info;
-
- info = (TWindow**)GetWRefCon(wind);
- SelectOrDeselectAllListItems((**info).theList, false);
- }
-
-
-
- /*----------------------------------------------------------------------------
- DoFind
-
- Handle the "Find" command for a group window.
-
- Entry: wind = pointer to group window.
-
- Exit: function result = error code.
- ----------------------------------------------------------------------------*/
-
- static OSErr DoFind (WindowPtr wind)
- {
- TWindow **info;
- ListHandle theList;
- Cell theCell;
- OSErr err = noErr;
-
- err = DoFindDialog();
- if (err != noErr) return err;
- info = (TWindow**)GetWRefCon(wind);
- theList = (**info).theList;
- SetPt(&theCell, 0, 0);
- if (!gPrefs.startFindAtBeginning) LGetSelect(true, &theCell, theList);
- return Find(wind, theCell);
- }
-
-
-
- /*----------------------------------------------------------------------------
- DoFindAgain
-
- Handle the "Find Again" command for a group window.
-
- Entry: wind = pointer to group window.
-
- Exit: function result = error code.
- ----------------------------------------------------------------------------*/
-
- static OSErr DoFindAgain (WindowPtr wind)
- {
- TWindow **info;
- ListHandle theList;
- Cell theCell;
-
- info = (TWindow**)GetWRefCon(wind);
- theList = (**info).theList;
- SetPt(&theCell, 0, 0);
- if (LGetSelect(true, &theCell, theList)) theCell.v++;
- return Find(wind, theCell);
- }
-
-
-
- /*----------------------------------------------------------------------------
- DoSubscribe
-
- Handle the "Subscribe" command for a group window.
-
- Entry: wind = pointer to full or new group window.
-
- Exit: function result = error code.
- ----------------------------------------------------------------------------*/
-
- static OSErr DoSubscribe (WindowPtr wind)
- {
- WindowPtr targetWind;
- TWindow **targetInfo;
- TWindowKind kind;
- OSErr err = noErr;
-
- targetWind = FrontWindow();
- while (targetWind != nil) {
- kind = GetMyWindowKind(targetWind);
- if (kind == kGroup) {
- targetInfo = (TWindow**)GetWRefCon(targetWind);
- if ((**targetInfo).groupKind == kUserGroup) break;
- }
- targetWind = (WindowPtr)((WindowPeek)targetWind)->nextWindow;
- }
-
- if (targetWind == nil) {
- err = MakeNewUntitledUserGroupWindow(&targetWind);
- if (err != noErr) return err;
- }
-
- return CopyOrMoveSelectedGroups(wind, targetWind, 0x7fff, true);
- }
-
-
-
- /*----------------------------------------------------------------------------
- DoUnsubscribe
-
- Handle the "Unsubscribe" command for a user group window.
-
- Entry: wind = pointer to group window.
-
- Exit: function result = error code.
- ----------------------------------------------------------------------------*/
-
- static OSErr DoUnsubscribe (WindowPtr wind)
- {
- return UnsubscribeSelected(wind);
- }
-
-
-
- /*----------------------------------------------------------------------------
- Activate
-
- Handle an activate event for a group window.
-
- Entry: wind = pointer to group window.
- act = true to activate, false to deactivate
- ----------------------------------------------------------------------------*/
-
- static void Activate (WindowPtr wind, Boolean act)
- {
- TWindow **info;
- Rect r;
-
- info = (TWindow**)GetWRefCon(wind);
- MyLActivate(act, (**info).theList);
- r = wind->portRect;
- r.top = r.bottom - 15;
- r.left = r.right - 15;
- InvalRect(&r);
- }
-
-
-
- /*----------------------------------------------------------------------------
- Update
-
- Handle an update event for a group window.
-
- Entry: wind = pointer to group window.
- ----------------------------------------------------------------------------*/
-
- static void Update (WindowPtr wind)
- {
- TWindow **info;
- ListHandle theList;
- short panelHeight, windWidth, numGroups;
- Rect r;
- FontInfo fontInfo;
- CStr255 str;
- CStr255 fmt;
-
- info = (TWindow**)GetWRefCon(wind);
- theList = (**info).theList;
- panelHeight = (**info).panelHeight;
-
- r = wind->portRect;
- r.top += panelHeight;
- ClipRect(&r);
- DrawGrowIcon(wind);
- ClipRect(&wind->portRect);
-
- windWidth = wind->portRect.right - wind->portRect.left;
- MoveTo(0, panelHeight-3);
- LineTo(windWidth, panelHeight-3);
- MoveTo(0, panelHeight-1);
- LineTo(windWidth, panelHeight-1);
-
- GetFontInfo(&fontInfo);
- numGroups = (**theList).dataBounds.bottom;
- if (numGroups == 1) {
- GetCString(kStrOneGroup, str);
- } else {
- GetCString(kStrNGroups, fmt);
- sprintf(str, fmt, numGroups);
- }
- c2pstr(str);
- TruncString(windWidth - 20, (StringPtr)str, smTruncEnd);
- MoveTo(10, fontInfo.ascent + 3);
- DrawString((StringPtr)str);
-
- LUpdate(wind->visRgn, (**info).theList);
- }
-
-
-
- /*----------------------------------------------------------------------------
- Mouse
-
- Handle a mouse down event in the content area of a group window.
-
- Entry: wind = pointer to group window.
- where = location of mouse down in local coords.
- modifiers = modifiers field from event record.
-
- Exit: function result = error code.
- ----------------------------------------------------------------------------*/
-
- static OSErr Mouse (WindowPtr wind, Point where, short modifiers)
- {
- TWindow **info;
- ListHandle theList;
- OSErr err = noErr;
- Boolean shift, command, option, doubleClick;
- Rect rView;
-
- info = (TWindow**) GetWRefCon(wind);
- theList = (**info).theList;
-
- shift = (modifiers & shiftKey) != 0;
- command = (modifiers & cmdKey) != 0;
- option = (modifiers & optionKey) != 0;
-
- if (where.v < (**info).panelHeight) {
- SelectOrDeselectAllListItems(theList, false);
- return noErr;
- }
-
- rView = (**theList).rView;
- if (where.v <= rView.top || where.v >= rView.bottom) return noErr;
- if (where.v >= rView.bottom - 1) where.v = rView.bottom - 2;
-
- if (!shift && !command && PtInListCell(where, theList)) {
- if (gHaveDragMgr) {
- gDragSrcWindow = wind;
- gFirstListClickCall = true;
- gClickLoopErr = noErr;
- (**theList).lClickLoop = gGroupListClickLoopUPP;
- } else {
- OldBeginListClick(nil);
- (**theList).lClickLoop = gOldListClickLoopUPP;
- }
- gDidDrag = false;
- doubleClick = MyLClickPossiblyInactive(where, modifiers, theList);
- if (doubleClick && !gDidDrag) {
- err = OpenSelectedCells(wind, option);
- if (err != noErr) return err;
- } else if (gHaveDragMgr) {
- if (gClickLoopErr != noErr) return gClickLoopErr;
- } else {
- err = OldEndListClick();
- if (err != noErr) return err;
- }
- } else {
- (**theList).lClickLoop = nil;
- MyLClickPossiblyInactive(where, modifiers, theList);
- }
-
- return noErr;
- }
-
-
-
- /*----------------------------------------------------------------------------
- Draggable
-
- Determine whether a mouse down event is on a draggable object in a
- group window.
-
- Entry: wind = pointer to group window.
- where = location of mouse down event, in local coordinates.
- modifiers = modifiers field from event record.
-
- Exit: function result = true if object is draggable.
- ----------------------------------------------------------------------------*/
-
- static Boolean Draggable (WindowPtr wind, Point where, short modifiers)
- {
- TWindow **info;
- ListHandle theList;
-
- if ((modifiers & shiftKey) != 0) return false;
- if ((modifiers & cmdKey) != 0) return false;
- info = (TWindow**)GetWRefCon(wind);
- theList = (**info).theList;
- return PtInListCell(where, theList);
- }
-
-
-
- /*----------------------------------------------------------------------------
- Key
-
- Handle a key down event for a group window.
-
- Entry: wind = pointer to group window.
- theChar = ASCII code of key.
- theKey = keyboard code of key.
- modifiers = modifiers field from event record.
-
- Exit: function result = error code.
- ----------------------------------------------------------------------------*/
-
- static OSErr Key (WindowPtr wind, unsigned char theChar, unsigned char theKey,
- short modifiers)
- {
- TWindow **info;
- ListHandle theList;
- Cell scrollIntoView;
- OSErr err = noErr;
- TKeypadKey keypadKey;
- Boolean isUpOrDownArrow;
-
- info = (TWindow**)GetWRefCon(wind);
- theList = (**info).theList;
- isUpOrDownArrow = theChar == upArrow || theChar == downArrow;
-
- if ((modifiers & cmdKey) != 0 && !isUpOrDownArrow) {
- SysBeep(0);
- return noErr;
- }
-
- if (gPrefs.keypadShortcuts && IsKeypadKey(theChar, theKey, &keypadKey)) {
- switch (keypadKey) {
- case kKeypadEqualKey:
- DoSelectAll(wind);
- return noErr;
- case kKeypadStarKey:
- return DoClose(wind);
- case kKeypadMinusKey:
- return DoMarkCommand(wind, false);
- case kKeypadPlusKey:
- return DoMarkCommand(wind, true);
- case kKeypadEnterKey:
- return DoNextGroup(wind);
- case kKeypadPeriodKey:
- return DoNextThread(wind);
- case kKeypad0Key:
- return DoNextArticle(wind);
- case kKeypad1Key:
- Scroll(wind, kScrollToEnd);
- return noErr;
- case kKeypad2Key:
- Scroll(wind, inDownButton);
- return noErr;
- case kKeypad3Key:
- Scroll(wind, inPageDown);
- return noErr;
- case kKeypad5Key:
- return DoNextArticle(wind);
- case kKeypad7Key:
- Scroll(wind, kScrollToHome);
- return noErr;
- case kKeypad8Key:
- Scroll(wind, inUpButton);
- return noErr;
- case kKeypad9Key:
- Scroll(wind, inPageUp);
- return noErr;
- default:
- SysBeep(0);
- return noErr;
- }
- }
-
- if (theChar == pageUpKey) {
- Scroll(wind, inPageUp);
- return noErr;
- }
- if (theChar == pageDownKey) {
- Scroll(wind, inPageDown);
- return noErr;
- }
- if (theChar == homeKey) {
- Scroll(wind, kScrollToHome);
- return noErr;
- }
- if (theChar == endKey) {
- Scroll(wind, kScrollToEnd);
- return noErr;
- }
- if (theChar == returnKey || theChar == enterKey) {
- return OpenSelectedCells(wind, (modifiers & optionKey) != 0);
- }
- if (isUpOrDownArrow) {
- ListArrowKey(theChar, modifiers, theList, &gPrevEvent, &scrollIntoView);
- HandleUpdate(wind);
- MyLScrollCellIntoView(scrollIntoView, theList);
- return noErr;
- }
- if (theChar == deleteKey) {
- if ((**info).groupKind == kUserGroup) return UnsubscribeSelected(wind);
- }
-
- if (gPrefs.keyboardShortcuts) {
-
- theChar = tolower(theChar);
-
- if (theChar == ' ' || theChar == 'n' || theChar == 'i') {
- return DoNextArticle(wind);
- }
-
- if (theChar == 't') {
- return DoNextThread(wind);
- }
-
- if (theChar == 'g' || theChar == 'j') {
- return DoNextGroup(wind);
- }
-
- if (theChar == 'w') {
- return DoClose(wind);
- }
-
- if (theChar == 'u') {
- return DoMarkCommand(wind, false);
- }
-
- if (theChar == 'm') {
- return DoMarkCommand(wind, true);
- }
-
- if (theChar == 'a') {
- DoSelectAll(wind);
- return noErr;
- }
-
- }
-
- SysBeep(0);
-
- return noErr;
- }
-
-
-
- /*----------------------------------------------------------------------------
- Grow
-
- Handle a mouse down event in the grow box of a group window.
-
- Entry: wind = pointer to group window.
- where = location of mouse down event, in global coordinates.
-
- Exit: function result = error code.
- ----------------------------------------------------------------------------*/
-
- static OSErr Grow (WindowPtr wind, Point where)
- {
- Rect sizeRect;
- long size;
- short width, height;
- TWindow **info;
-
- SetRect(&sizeRect, kMinWindowWidth, MinHeight(wind), 0x7fff, 0x7fff);
- size = GrowWindow(wind, where, &sizeRect);
-
- if (size != 0) {
- width = LoWord(size);
- height = HiWord(size);
- FixHeight(wind, &height);
- SizeWindow(wind, width, height, false);
- ResizeContents(wind);
- info = (TWindow**)GetWRefCon(wind);
- (**info).windPosValid = true;
- (**info).movedSinceLastSave = true;
- }
-
- return noErr;
- }
-
-
-
- /*----------------------------------------------------------------------------
- Zoom
-
- Zoom a group window.
-
- Entry: wind = pointer to group window.
- zoomDir = zoom direction = inZoomIn or inZoomOut.
-
- Exit: function result = error code.
- ----------------------------------------------------------------------------*/
-
- static OSErr Zoom (WindowPtr wind, short zoomDir)
- {
- TWindow **info;
- ListHandle theList;
- TGroup **groupArray;
- short width, height, lineHeight, minHeight, panelHeight;
- short groupNameWidth, maxGroupNameWidth, index, cellDataLen, numCells;
- Cell theCell;
- char *groupName;
- Rect zoomRect;
- WStateData **wState;
- long longHeight;
- char state1, state2;
-
- info = (TWindow**)GetWRefCon(wind);
-
- wState = (WStateData**)((WindowPeek)wind)->dataHandle;
- if (zoomDir == inZoomOut) {
- theList = (**info).theList;
- panelHeight = (**info).panelHeight;
- groupArray = (**info).groupArray;
- numCells = (**theList).dataBounds.bottom;
- lineHeight = (**theList).cellSize.v;
-
- if ((**info).groupKind == kFullGroup && gPrefs.maxGroupNameWidth != 0) {
- maxGroupNameWidth = gPrefs.maxGroupNameWidth;
- } else {
- maxGroupNameWidth = 0;
- theCell.h = 0;
- state1 = MyHGetState(groupArray);
- state2 = MyHGetState(gGroupNames);
- MyHLock(groupArray);
- MyHLock(gGroupNames);
- for (theCell.v=0; theCell.v < numCells; theCell.v++) {
- cellDataLen = 2;
- LGetCell(&index, &cellDataLen, theCell, theList);
- groupName = *gGroupNames + (*groupArray)[index].nameOffset;
- groupNameWidth = TextWidth(groupName, 0, strlen(groupName));
- if (groupNameWidth > maxGroupNameWidth) maxGroupNameWidth = groupNameWidth;
- }
- MyHSetState(groupArray, state1);
- MyHSetState(gGroupNames, state2);
- if ((**info).groupKind == kFullGroup) gPrefs.maxGroupNameWidth = maxGroupNameWidth;
- }
- width = maxGroupNameWidth + (**info).groupNameHCoord + 24;
- if (width < kMinWindowWidth) width = kMinWindowWidth;
-
- longHeight = (long)((**theList).dataBounds.bottom -
- (**theList).dataBounds.top) * (long)lineHeight;
- longHeight += panelHeight + 15;
- if (longHeight > 0x7fff) {
- height = 0x7fff;
- } else {
- height = longHeight;
- minHeight = MinHeight(wind);
- if (height < minHeight) height = minHeight;
- }
-
- CalculateZoomRect(wind, width, height, &zoomRect, gPrefs.dontCoverFinderIcons);
- height = zoomRect.bottom - zoomRect.top;
- FixHeight(wind, &height);
- zoomRect.bottom = zoomRect.top + height;
- (**wState).stdState = zoomRect;
- if (WindRectEqualRect(wind, &zoomRect)) return noErr;
- }
-
- EraseRect(&wind->portRect);
- ZoomWindow(wind, zoomDir, false);
- ResizeContents(wind);
- (**info).windPosValid = true;
- (**info).movedSinceLastSave = true;
- return noErr;
- }
-
-
-
- /*----------------------------------------------------------------------------
- Command
-
- Handle a command for a group window.
-
- Entry: wind = pointer to group window.
- menu = the menu.
- item = the item.
- modifiers = modifiers field from event record.
-
- Exit: function result = error code.
- ----------------------------------------------------------------------------*/
-
- static OSErr Command (WindowPtr wind, short menu, short item, short modifiers)
- {
- OSErr err = noErr;
-
- switch (menu) {
-
- case kFileMenu:
-
- switch (item) {
- case kSaveItem:
- err = DoSave(wind);
- break;
- case kSaveAsItem:
- err = DoSaveAs(wind);
- break;
- }
- break;
-
- case kEditMenu:
-
- switch (item) {
- case kCutItem:
- err = DoCut(wind);
- break;
- case kCopyItem:
- err = DoCopy(wind);
- break;
- case kPasteItem:
- err = DoPaste(wind);
- break;
- case kClearItem:
- err = DoClear(wind);
- break;
- case kSelectAllItem:
- DoSelectAll(wind);
- break;
- case kDeselectAllItem:
- DoDeselectAll(wind);
- break;
- case kFindItem:
- err = DoFind(wind);
- break;
- case kFindAgainItem:
- err = DoFindAgain(wind);
- break;
- }
- break;
-
- case kNewsMenu:
-
- switch (item) {
- case kNextArticleItem:
- err = DoNextArticle(wind);
- break;
- case kNextThreadItem:
- err = DoNextThread(wind);
- break;
- case kNextGroupItem:
- err = DoNextGroup(wind);
- break;
- case kMarkReadItem:
- err = DoMarkCommand(wind, true);
- break;
- case kMarkUnreadItem:
- err = DoMarkCommand(wind, false);
- break;
- case kCheckForNewArticlesItem:
- err = DoCheckNewArticles(wind);
- break;
- }
- break;
-
- case kSpecialMenu:
- switch (item) {
- case kSendGroupListToHostItem:
- err = DoSendGroupListToHost(wind, false);
- break;
- case kSearchItem:
- err = DoSearch(wind);
- break;
- case kSubscribeItem:
- err = DoSubscribe(wind);
- break;
- case kUnsubscribeItem:
- err = DoUnsubscribe(wind);
- break;
- }
- break;
- }
-
- return err;
- }
-
-
-
- /*----------------------------------------------------------------------------
- Close
-
- Close a group window.
-
- Entry: wind = pointer to group window.
-
- Exit: function result = error code.
- ----------------------------------------------------------------------------*/
-
- static OSErr Close (WindowPtr wind)
- {
- TWindow **info;
- TGroupWindowKind groupKind;
- OSErr err = noErr;
-
- info = (TWindow**)GetWRefCon(wind);
- groupKind = (**info).groupKind;
-
- if (groupKind == kFullGroup && gFullGroupWindow != nil)
- return DoShowHideFullGroupList();
-
- if (groupKind == kUserGroup) {
- if ((**info).changed && (**info).autoFetched && gPrefs.autoFetchNewsrc) {
- err = DoSendGroupListToHost(wind, true);
- if (err != noErr) return err;
- }
- if ((**info).changed) {
- err = CheckForSave(wind);
- if (err != noErr) return err;
- }
- }
-
- err = SaveWindPosToFile(wind);
- if (err != noErr) return err;
-
- while ((**info).childList != nil) {
- err = DoClose((**(**info).childList).childWindow);
- if (err != noErr) return err;
- }
-
- if ((**info).autoFetched)
- SaveWindPos(wind, &gPrefs.autoFetchWindPos);
-
- DisposeGroupArray((**info).groupArray, (**info).numGroups);
-
- LDispose((**info).theList);
- MyDisposeHandle((**info).unsubscribed);
- MyDisposeHandle((**info).alias);
- MyDisposeHandle(info);
-
- if (groupKind == kUserGroup && gHaveDragMgr) {
- RemoveTrackingHandler(gHandleTrackingUPP, wind);
- RemoveReceiveHandler(gHandleReceiveUPP, wind);
- }
-
- MyDisposeWindow(wind);
- return noErr;
- }
-
-
-
- /*----------------------------------------------------------------------------
- Idle
-
- Handle idle time tasks for a group window.
-
- Entry: wind = pointer to group window.
-
- Exit: cursorRgn = cursor region for WaitNextEvent mouse moved events.
- ----------------------------------------------------------------------------*/
-
- static void Idle (WindowPtr wind, RgnHandle cursorRgn)
- {
- TWindow **info, **theWindInfo;
- WindowPtr theWind;
- TGroupWindowKind groupKind;
- ListHandle theList;
- unsigned long fileEnabled, editEnabled, newsEnabled, specialEnabled, windEnabled;
- short numOpenUserGroupWindows;
- long scrapOffset;
-
- info = (TWindow**)GetWRefCon(wind);
- groupKind = (**info).groupKind;
- theList = (**info).theList;
-
- SetCursor(&qd.arrow);
-
- switch (groupKind) {
- case kFullGroup:
- fileEnabled = kGroupFileEnabled;
- editEnabled = kGroupEditEnabled;
- newsEnabled = kGroupNewsEnabled;
- specialEnabled = kGroupSpecialEnabled;
- windEnabled = kGroupWindEnabled;
- break;
- case kNewGroup:
- fileEnabled = kNewGroupFileEnabled;
- editEnabled = kNewGroupEditEnabled;
- newsEnabled = kNewGroupNewsEnabled;
- specialEnabled = kNewGroupSpecialEnabled;
- windEnabled = kNewGroupWindEnabled;
- break;
- case kUserGroup:
- fileEnabled = kUserGroupFileEnabled;
- if ((**info).alias != nil && !(**info).changed)
- fileEnabled &= ~kSaveMask;
- editEnabled = kUserGroupEditEnabled;
- newsEnabled = kUserGroupNewsEnabled;
- specialEnabled = kUserGroupSpecialEnabled;
- windEnabled = kUserGroupWindEnabled;
- break;
- }
- if (!ListHasSelectedCell(theList)) {
- editEnabled &= ~(kCutMask | kCopyMask | kClearMask | kDeselectAllMask);
- newsEnabled &= ~(kMarkReadMask | kMarkUnreadMask);
- specialEnabled &= ~(kSearchMask | kSubscribeMask | kUnsubscribeMask);
- }
- if (GetScrap(nil, kNewsWatcherSignature, &scrapOffset) <= 0)
- editEnabled &= ~kPasteMask;
- if ((**theList).dataBounds.bottom == 0) {
- editEnabled &= ~kSelectAllMask;
- newsEnabled &= ~kCheckForNewArticlesMask;
- }
- if ((specialEnabled & kSubscribeMask) != 0) {
- numOpenUserGroupWindows = 0;
- for (theWind = FrontWindow(); theWind != nil;
- theWind = (WindowPtr)((WindowPeek)theWind)->nextWindow)
- {
- if (GetMyWindowKind(theWind) == kGroup) {
- theWindInfo = (TWindow**)GetWRefCon(theWind);
- if ((**theWindInfo).groupKind == kUserGroup) {
- numOpenUserGroupWindows++;
- if (numOpenUserGroupWindows > 1) {
- specialEnabled &= ~kSubscribeMask;
- break;
- }
- }
- }
- }
- }
- if (*gFindPattern == 0) editEnabled &= ~kFindAgainMask;
- SetMenusTo(kAppleAllEnabled, fileEnabled, editEnabled, newsEnabled,
- specialEnabled, windEnabled);
- }
-
-
-
- /*----------------------------------------------------------------------------
- Help
-
- Handle help balloons for a group window.
-
- Entry: wind = pointer to group window.
- where = current mouse location in local coordinates.
- ----------------------------------------------------------------------------*/
-
- static void Help (WindowPtr wind, Point where)
- {
- TWindow **info;
- TGroupWindowKind groupKind;
- short index, groupNameHCoord;
- Rect r;
-
- if (DoSizeBoxAndVerticalScrollBarBalloons(wind, where)) return;
- info = (TWindow**)GetWRefCon(wind);
- groupKind = (**info).groupKind;
- r = wind->portRect;
- r.right -= 15;
- r.bottom -= 15;
- r.top = (**info).panelHeight;
- if (!PtInRect(where, &r)) return;
- switch (groupKind) {
- case kFullGroup:
- index = 10;
- break;
- case kNewGroup:
- index = 11;
- break;
- case kUserGroup:
- groupNameHCoord = (**info).groupNameHCoord;
- if (where.h < groupNameHCoord) {
- index = 13;
- r.right = groupNameHCoord;
- } else {
- index = 12;
- r.left = groupNameHCoord;
- }
- break;
- }
- ShowHelpBalloon(where, &r, index);
- }
-
-
-
- /*----------------------------------------------------------------------------
- InitGroupDispatchTable
-
- Initialize the dispatch table for group windows.
- ----------------------------------------------------------------------------*/
-
- void InitGroupDispatchTable (void)
- {
- TDispatch *d;
-
- d = &gDispatch[kGroup];
-
- d->activate = Activate;
- d->update = Update;
- d->mouse = Mouse;
- d->draggable = Draggable;
- d->key = Key;
- d->grow = Grow;
- d->zoom = Zoom;
- d->command = Command;
- d->close = Close;
- d->idle = Idle;
- d->help = Help;
-
- gGroupListClickLoopUPP = NewListClickLoopProc(GroupListClickLoop);
- gOldListClickLoopUPP = NewListClickLoopProc(OldListClickLoop);
- gHandleTrackingUPP = NewDragTrackingHandlerProc(HandleTracking);
- gHandleReceiveUPP = NewDragReceiveHandlerProc(HandleReceive);
- }
-